<?php

require_once 'PipesImpl/Model.php';
require_once 'PipesImpl/Model/Meta.php';
require_once 'Pipes/Form/Container.php';
require_once 'Pipes/Form/Element.php';
require_once 'Pipes/Form/Controls.php';
require_once 'Pipes/Xml/Document.php';
require_once 'Pipes/Xml/Renderer.php';
require_once 'Pipes/Xml/Xpath.php';

class Pipes_Form_Factory
{
    private $_form = null;
    private $_model = null;
    private $_capture = null;

    public function __construct(PipesImpl_Model $model, $action = null)
    {
        $this->_model = $model;
        $this->_form = new Pipes_Form_Container();
        if (!is_null($action)) {
            $this->action($action);
        }

        ob_start();
    }

    public function action($uri) {
        $this->_form->action($uri);
    }
    
    public function render()
    {
        $string = ob_get_clean();
        if (!empty($string)) {
            $this->_capture = new Pipes_Xml_Document();
            $xml = '<div xmlns:pipes="http://phpinpipes.org/schema/v1">' . $string . '</div>';
            $this->_capture->loadXML($xml);
        }

        $propertyNames = array_merge(
            array_keys($this->_model->getColumns()),
            $this->_model->listRelationships()
        );

        foreach ($propertyNames as $propertyName) {
            if (!is_null($this->_capture)) {
                $xpath = new Pipes_Xml_Xpath($this->_capture);
                $query = "//*[@pipes:for='{$propertyName}']";
                $element = $xpath->query($query);
                if ($element->length > 0) {
                    $document = new Pipes_Xml_Document;
                    $input = $document->importNode($element->item(0), true);
                    $document->appendChild($input);
                    
                    $renderable = new Pipes_Xml_Renderer($document);
                    $this->_form->add($renderable);

                    

                    // break out of this as we've done our job
                    continue;
                }
            }
            
            // skip if its a relationship and custom code isn't specified
            if (in_array($propertyName, $this->_model->listRelationships())) {
                continue;
            }
            $this->_form->add(new Pipes_Form_Element($this->_model, $propertyName));
        }
        
        $this->_form->add(new Pipes_Form_Controls($this->_model));
        
        return $this->_form->render();
    }
}
